﻿using Kalman;
using Kalman.Jwt;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using NLog;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Reflection;
using System.Text;

namespace QuDao.Api
{
    /// <summary>
    /// API授权
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class ApiAuthAttribute : Attribute, IAuthorizationFilter
    {
        /// <summary>
        /// 认证方式（1-JWT令牌认证，2-签名认证，4-IP白名单认证），给客户端应用指定认证模式
        /// </summary>
        public AuthMethod AuthMethod { get; set; } = AuthMethod.Jwt;

        /// <summary>
        /// 是否调试模式（忽略认证）
        /// </summary>
        public bool IsDebug { get; set; } = false;

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var env = ServiceLocator.Instance.GetHostingEnvironment();
            if (IsDebug && env.IsDevelopment()) return;

            var log = LogManager.GetCurrentClassLogger();
            var action = context.ActionDescriptor as ControllerActionDescriptor;
            var allowAnonymous = action.MethodInfo.GetCustomAttribute<AllowAnonymousAttribute>();
            if (allowAnonymous != null) return; //先判断Action方法是不是有附加匿名访问特性

            allowAnonymous = action.ControllerTypeInfo.GetCustomAttribute<AllowAnonymousAttribute>();
            if (allowAnonymous != null) return; //再判断控制器上是不是有附加匿名访问特性

            IActionResult result = null;
            try
            {
                if ((AuthMethod & AuthMethod.Jwt) > 0) result = context.JwtAuth();
                if ((AuthMethod & AuthMethod.Sign) > 0) result = context.SignAuth();
                if ((AuthMethod & AuthMethod.IP) > 0) result = context.IpAuth();
            }
            catch (Exception ex)
            {
                result = new UnauthorizedObjectResult(new { code = "401", msg = ex.Message });
                log.Error(ex, "API认证发生未知错误");
            }

            if (result != null) context.Result = result;
            return;
        }

        
    }
}
